diff options
author | Mark Brown <broonie@linaro.org> | 2013-09-01 08:49:03 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-09-01 08:49:03 -0400 |
commit | 68aa4cb3374a5f47fe1f7b31e0b5893826c05c69 (patch) | |
tree | aa350fff2ef8ef496d46820487198e9bbfe2bf77 /drivers/spi/spi-xilinx.c | |
parent | 11c28cfc1e4f32dc6d02373a1e80d7e83584ed21 (diff) | |
parent | b5f9a9d5113efe11a3b9dad600a6f833274da595 (diff) |
Merge remote-tracking branch 'spi/topic/pdata' into spi-next
Diffstat (limited to 'drivers/spi/spi-xilinx.c')
-rw-r--r-- | drivers/spi/spi-xilinx.c | 172 |
1 files changed, 66 insertions, 106 deletions
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index fb56fcfdf65e..0bf1b2c457a1 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c | |||
@@ -80,10 +80,9 @@ struct xilinx_spi { | |||
80 | /* bitbang has to be first */ | 80 | /* bitbang has to be first */ |
81 | struct spi_bitbang bitbang; | 81 | struct spi_bitbang bitbang; |
82 | struct completion done; | 82 | struct completion done; |
83 | struct resource mem; /* phys mem */ | ||
84 | void __iomem *regs; /* virt. address of the control registers */ | 83 | void __iomem *regs; /* virt. address of the control registers */ |
85 | 84 | ||
86 | u32 irq; | 85 | int irq; |
87 | 86 | ||
88 | u8 *rx_ptr; /* pointer in the Tx buffer */ | 87 | u8 *rx_ptr; /* pointer in the Tx buffer */ |
89 | const u8 *tx_ptr; /* pointer in the Rx buffer */ | 88 | const u8 *tx_ptr; /* pointer in the Rx buffer */ |
@@ -340,17 +339,34 @@ static const struct of_device_id xilinx_spi_of_match[] = { | |||
340 | }; | 339 | }; |
341 | MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); | 340 | MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); |
342 | 341 | ||
343 | struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, | 342 | static int xilinx_spi_probe(struct platform_device *pdev) |
344 | u32 irq, s16 bus_num, int num_cs, int bits_per_word) | ||
345 | { | 343 | { |
346 | struct spi_master *master; | ||
347 | struct xilinx_spi *xspi; | 344 | struct xilinx_spi *xspi; |
348 | int ret; | 345 | struct xspi_platform_data *pdata; |
346 | struct resource *res; | ||
347 | int ret, num_cs = 0, bits_per_word = 8; | ||
348 | struct spi_master *master; | ||
349 | u32 tmp; | 349 | u32 tmp; |
350 | u8 i; | ||
351 | |||
352 | pdata = dev_get_platdata(&pdev->dev); | ||
353 | if (pdata) { | ||
354 | num_cs = pdata->num_chipselect; | ||
355 | bits_per_word = pdata->bits_per_word; | ||
356 | } else { | ||
357 | of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits", | ||
358 | &num_cs); | ||
359 | } | ||
350 | 360 | ||
351 | master = spi_alloc_master(dev, sizeof(struct xilinx_spi)); | 361 | if (!num_cs) { |
362 | dev_err(&pdev->dev, | ||
363 | "Missing slave select configuration data\n"); | ||
364 | return -EINVAL; | ||
365 | } | ||
366 | |||
367 | master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi)); | ||
352 | if (!master) | 368 | if (!master) |
353 | return NULL; | 369 | return -ENODEV; |
354 | 370 | ||
355 | /* the spi->mode bits understood by this driver: */ | 371 | /* the spi->mode bits understood by this driver: */ |
356 | master->mode_bits = SPI_CPOL | SPI_CPHA; | 372 | master->mode_bits = SPI_CPOL | SPI_CPHA; |
@@ -362,22 +378,16 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, | |||
362 | xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; | 378 | xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; |
363 | init_completion(&xspi->done); | 379 | init_completion(&xspi->done); |
364 | 380 | ||
365 | if (!request_mem_region(mem->start, resource_size(mem), | 381 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
366 | XILINX_SPI_NAME)) | 382 | xspi->regs = devm_ioremap_resource(&pdev->dev, res); |
383 | if (IS_ERR(xspi->regs)) { | ||
384 | ret = PTR_ERR(xspi->regs); | ||
367 | goto put_master; | 385 | goto put_master; |
368 | |||
369 | xspi->regs = ioremap(mem->start, resource_size(mem)); | ||
370 | if (xspi->regs == NULL) { | ||
371 | dev_warn(dev, "ioremap failure\n"); | ||
372 | goto map_failed; | ||
373 | } | 386 | } |
374 | 387 | ||
375 | master->bus_num = bus_num; | 388 | master->bus_num = pdev->dev.id; |
376 | master->num_chipselect = num_cs; | 389 | master->num_chipselect = num_cs; |
377 | master->dev.of_node = dev->of_node; | 390 | master->dev.of_node = pdev->dev.of_node; |
378 | |||
379 | xspi->mem = *mem; | ||
380 | xspi->irq = irq; | ||
381 | 391 | ||
382 | /* | 392 | /* |
383 | * Detect endianess on the IP via loop bit in CR. Detection | 393 | * Detect endianess on the IP via loop bit in CR. Detection |
@@ -407,113 +417,63 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, | |||
407 | } else if (xspi->bits_per_word == 32) { | 417 | } else if (xspi->bits_per_word == 32) { |
408 | xspi->tx_fn = xspi_tx32; | 418 | xspi->tx_fn = xspi_tx32; |
409 | xspi->rx_fn = xspi_rx32; | 419 | xspi->rx_fn = xspi_rx32; |
410 | } else | 420 | } else { |
411 | goto unmap_io; | 421 | ret = -EINVAL; |
412 | 422 | goto put_master; | |
423 | } | ||
413 | 424 | ||
414 | /* SPI controller initializations */ | 425 | /* SPI controller initializations */ |
415 | xspi_init_hw(xspi); | 426 | xspi_init_hw(xspi); |
416 | 427 | ||
428 | xspi->irq = platform_get_irq(pdev, 0); | ||
429 | if (xspi->irq < 0) { | ||
430 | ret = xspi->irq; | ||
431 | goto put_master; | ||
432 | } | ||
433 | |||
417 | /* Register for SPI Interrupt */ | 434 | /* Register for SPI Interrupt */ |
418 | ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); | 435 | ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0, |
436 | dev_name(&pdev->dev), xspi); | ||
419 | if (ret) | 437 | if (ret) |
420 | goto unmap_io; | 438 | goto put_master; |
421 | 439 | ||
422 | ret = spi_bitbang_start(&xspi->bitbang); | 440 | ret = spi_bitbang_start(&xspi->bitbang); |
423 | if (ret) { | 441 | if (ret) { |
424 | dev_err(dev, "spi_bitbang_start FAILED\n"); | 442 | dev_err(&pdev->dev, "spi_bitbang_start FAILED\n"); |
425 | goto free_irq; | 443 | goto put_master; |
426 | } | ||
427 | |||
428 | dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", | ||
429 | (unsigned long long)mem->start, xspi->regs, xspi->irq); | ||
430 | return master; | ||
431 | |||
432 | free_irq: | ||
433 | free_irq(xspi->irq, xspi); | ||
434 | unmap_io: | ||
435 | iounmap(xspi->regs); | ||
436 | map_failed: | ||
437 | release_mem_region(mem->start, resource_size(mem)); | ||
438 | put_master: | ||
439 | spi_master_put(master); | ||
440 | return NULL; | ||
441 | } | ||
442 | EXPORT_SYMBOL(xilinx_spi_init); | ||
443 | |||
444 | void xilinx_spi_deinit(struct spi_master *master) | ||
445 | { | ||
446 | struct xilinx_spi *xspi; | ||
447 | |||
448 | xspi = spi_master_get_devdata(master); | ||
449 | |||
450 | spi_bitbang_stop(&xspi->bitbang); | ||
451 | free_irq(xspi->irq, xspi); | ||
452 | iounmap(xspi->regs); | ||
453 | |||
454 | release_mem_region(xspi->mem.start, resource_size(&xspi->mem)); | ||
455 | spi_master_put(xspi->bitbang.master); | ||
456 | } | ||
457 | EXPORT_SYMBOL(xilinx_spi_deinit); | ||
458 | |||
459 | static int xilinx_spi_probe(struct platform_device *dev) | ||
460 | { | ||
461 | struct xspi_platform_data *pdata; | ||
462 | struct resource *r; | ||
463 | int irq, num_cs = 0, bits_per_word = 8; | ||
464 | struct spi_master *master; | ||
465 | u8 i; | ||
466 | |||
467 | pdata = dev->dev.platform_data; | ||
468 | if (pdata) { | ||
469 | num_cs = pdata->num_chipselect; | ||
470 | bits_per_word = pdata->bits_per_word; | ||
471 | } | ||
472 | |||
473 | #ifdef CONFIG_OF | ||
474 | if (dev->dev.of_node) { | ||
475 | const __be32 *prop; | ||
476 | int len; | ||
477 | |||
478 | /* number of slave select bits is required */ | ||
479 | prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits", | ||
480 | &len); | ||
481 | if (prop && len >= sizeof(*prop)) | ||
482 | num_cs = __be32_to_cpup(prop); | ||
483 | } | ||
484 | #endif | ||
485 | |||
486 | if (!num_cs) { | ||
487 | dev_err(&dev->dev, "Missing slave select configuration data\n"); | ||
488 | return -EINVAL; | ||
489 | } | 444 | } |
490 | 445 | ||
491 | 446 | dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", | |
492 | r = platform_get_resource(dev, IORESOURCE_MEM, 0); | 447 | (unsigned long long)res->start, xspi->regs, xspi->irq); |
493 | if (!r) | ||
494 | return -ENODEV; | ||
495 | |||
496 | irq = platform_get_irq(dev, 0); | ||
497 | if (irq < 0) | ||
498 | return -ENXIO; | ||
499 | |||
500 | master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs, | ||
501 | bits_per_word); | ||
502 | if (!master) | ||
503 | return -ENODEV; | ||
504 | 448 | ||
505 | if (pdata) { | 449 | if (pdata) { |
506 | for (i = 0; i < pdata->num_devices; i++) | 450 | for (i = 0; i < pdata->num_devices; i++) |
507 | spi_new_device(master, pdata->devices + i); | 451 | spi_new_device(master, pdata->devices + i); |
508 | } | 452 | } |
509 | 453 | ||
510 | platform_set_drvdata(dev, master); | 454 | platform_set_drvdata(pdev, master); |
511 | return 0; | 455 | return 0; |
456 | |||
457 | put_master: | ||
458 | spi_master_put(master); | ||
459 | |||
460 | return ret; | ||
512 | } | 461 | } |
513 | 462 | ||
514 | static int xilinx_spi_remove(struct platform_device *dev) | 463 | static int xilinx_spi_remove(struct platform_device *pdev) |
515 | { | 464 | { |
516 | xilinx_spi_deinit(platform_get_drvdata(dev)); | 465 | struct spi_master *master = platform_get_drvdata(pdev); |
466 | struct xilinx_spi *xspi = spi_master_get_devdata(master); | ||
467 | void __iomem *regs_base = xspi->regs; | ||
468 | |||
469 | spi_bitbang_stop(&xspi->bitbang); | ||
470 | |||
471 | /* Disable all the interrupts just in case */ | ||
472 | xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET); | ||
473 | /* Disable the global IPIF interrupt */ | ||
474 | xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET); | ||
475 | |||
476 | spi_master_put(xspi->bitbang.master); | ||
517 | 477 | ||
518 | return 0; | 478 | return 0; |
519 | } | 479 | } |