of_mmc_spi.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * OpenFirmware bindings for the MMC-over-SPI driver
  4. *
  5. * Copyright (c) MontaVista Software, Inc. 2008.
  6. *
  7. * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/device.h>
  12. #include <linux/slab.h>
  13. #include <linux/irq.h>
  14. #include <linux/of.h>
  15. #include <linux/of_irq.h>
  16. #include <linux/spi/spi.h>
  17. #include <linux/spi/mmc_spi.h>
  18. #include <linux/mmc/core.h>
  19. #include <linux/mmc/host.h>
  20. MODULE_DESCRIPTION("OpenFirmware bindings for the MMC-over-SPI driver");
  21. MODULE_LICENSE("GPL");
  22. struct of_mmc_spi {
  23. struct mmc_spi_platform_data pdata;
  24. int detect_irq;
  25. };
  26. static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
  27. {
  28. return container_of(dev->platform_data, struct of_mmc_spi, pdata);
  29. }
  30. static int of_mmc_spi_init(struct device *dev,
  31. irqreturn_t (*irqhandler)(int, void *), void *mmc)
  32. {
  33. struct of_mmc_spi *oms = to_of_mmc_spi(dev);
  34. return request_threaded_irq(oms->detect_irq, NULL, irqhandler,
  35. IRQF_ONESHOT, dev_name(dev), mmc);
  36. }
  37. static void of_mmc_spi_exit(struct device *dev, void *mmc)
  38. {
  39. struct of_mmc_spi *oms = to_of_mmc_spi(dev);
  40. free_irq(oms->detect_irq, mmc);
  41. }
  42. struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
  43. {
  44. struct mmc_host *mmc = dev_get_drvdata(&spi->dev);
  45. struct device *dev = &spi->dev;
  46. struct of_mmc_spi *oms;
  47. if (dev->platform_data || !dev_fwnode(dev))
  48. return dev->platform_data;
  49. oms = kzalloc_obj(*oms);
  50. if (!oms)
  51. return NULL;
  52. if (mmc_of_parse_voltage(mmc, &oms->pdata.ocr_mask) < 0)
  53. goto err_ocr;
  54. oms->detect_irq = spi->irq;
  55. if (oms->detect_irq > 0) {
  56. oms->pdata.init = of_mmc_spi_init;
  57. oms->pdata.exit = of_mmc_spi_exit;
  58. } else {
  59. oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
  60. }
  61. if (device_property_read_bool(dev, "cap-sd-highspeed"))
  62. oms->pdata.caps |= MMC_CAP_SD_HIGHSPEED;
  63. if (device_property_read_bool(dev, "cap-mmc-highspeed"))
  64. oms->pdata.caps |= MMC_CAP_MMC_HIGHSPEED;
  65. dev->platform_data = &oms->pdata;
  66. return dev->platform_data;
  67. err_ocr:
  68. kfree(oms);
  69. return NULL;
  70. }
  71. EXPORT_SYMBOL(mmc_spi_get_pdata);
  72. void mmc_spi_put_pdata(struct spi_device *spi)
  73. {
  74. struct device *dev = &spi->dev;
  75. struct of_mmc_spi *oms = to_of_mmc_spi(dev);
  76. if (!dev->platform_data || !dev_fwnode(dev))
  77. return;
  78. kfree(oms);
  79. dev->platform_data = NULL;
  80. }
  81. EXPORT_SYMBOL(mmc_spi_put_pdata);