1aad5f19eSAndy Shevchenko // SPDX-License-Identifier: GPL-2.0-or-later 29c43df57SAnton Vorontsov /* 39c43df57SAnton Vorontsov * OpenFirmware bindings for the MMC-over-SPI driver 49c43df57SAnton Vorontsov * 59c43df57SAnton Vorontsov * Copyright (c) MontaVista Software, Inc. 2008. 69c43df57SAnton Vorontsov * 79c43df57SAnton Vorontsov * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 89c43df57SAnton Vorontsov */ 99c43df57SAnton Vorontsov 109c43df57SAnton Vorontsov #include <linux/kernel.h> 119c43df57SAnton Vorontsov #include <linux/module.h> 129c43df57SAnton Vorontsov #include <linux/device.h> 135a0e3ad6STejun Heo #include <linux/slab.h> 14b2fce6adSDavid Miller #include <linux/irq.h> 159c43df57SAnton Vorontsov #include <linux/of.h> 16b2fce6adSDavid Miller #include <linux/of_irq.h> 179c43df57SAnton Vorontsov #include <linux/spi/spi.h> 189c43df57SAnton Vorontsov #include <linux/spi/mmc_spi.h> 199c43df57SAnton Vorontsov #include <linux/mmc/core.h> 209c43df57SAnton Vorontsov #include <linux/mmc/host.h> 219c43df57SAnton Vorontsov 2202d9e58eSGrant Likely MODULE_LICENSE("GPL"); 2302d9e58eSGrant Likely 249c43df57SAnton Vorontsov struct of_mmc_spi { 25290293edSEsben Haabendal int detect_irq; 269c43df57SAnton Vorontsov struct mmc_spi_platform_data pdata; 279c43df57SAnton Vorontsov }; 289c43df57SAnton Vorontsov 299c43df57SAnton Vorontsov static struct of_mmc_spi *to_of_mmc_spi(struct device *dev) 309c43df57SAnton Vorontsov { 319c43df57SAnton Vorontsov return container_of(dev->platform_data, struct of_mmc_spi, pdata); 329c43df57SAnton Vorontsov } 339c43df57SAnton Vorontsov 34290293edSEsben Haabendal static int of_mmc_spi_init(struct device *dev, 35290293edSEsben Haabendal irqreturn_t (*irqhandler)(int, void *), void *mmc) 36290293edSEsben Haabendal { 37290293edSEsben Haabendal struct of_mmc_spi *oms = to_of_mmc_spi(dev); 38290293edSEsben Haabendal 3960b71f60Ssaurabh return request_threaded_irq(oms->detect_irq, NULL, irqhandler, 4060b71f60Ssaurabh IRQF_ONESHOT, dev_name(dev), mmc); 41290293edSEsben Haabendal } 42290293edSEsben Haabendal 43290293edSEsben Haabendal static void of_mmc_spi_exit(struct device *dev, void *mmc) 44290293edSEsben Haabendal { 45290293edSEsben Haabendal struct of_mmc_spi *oms = to_of_mmc_spi(dev); 46290293edSEsben Haabendal 47290293edSEsben Haabendal free_irq(oms->detect_irq, mmc); 48290293edSEsben Haabendal } 49290293edSEsben Haabendal 509c43df57SAnton Vorontsov struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) 519c43df57SAnton Vorontsov { 526dab809bSAndy Shevchenko struct mmc_host *mmc = dev_get_drvdata(&spi->dev); 539c43df57SAnton Vorontsov struct device *dev = &spi->dev; 549c43df57SAnton Vorontsov struct of_mmc_spi *oms; 559c43df57SAnton Vorontsov 56*edd60214SAndy Shevchenko if (dev->platform_data || !dev_fwnode(dev)) 579c43df57SAnton Vorontsov return dev->platform_data; 589c43df57SAnton Vorontsov 599c43df57SAnton Vorontsov oms = kzalloc(sizeof(*oms), GFP_KERNEL); 609c43df57SAnton Vorontsov if (!oms) 619c43df57SAnton Vorontsov return NULL; 629c43df57SAnton Vorontsov 636c857ccfSAndy Shevchenko if (mmc_of_parse_voltage(mmc, &oms->pdata.ocr_mask) < 0) 649c43df57SAnton Vorontsov goto err_ocr; 659c43df57SAnton Vorontsov 667240803bSAndy Shevchenko oms->detect_irq = spi->irq; 677240803bSAndy Shevchenko if (oms->detect_irq > 0) { 68290293edSEsben Haabendal oms->pdata.init = of_mmc_spi_init; 69290293edSEsben Haabendal oms->pdata.exit = of_mmc_spi_exit; 70290293edSEsben Haabendal } else { 719c43df57SAnton Vorontsov oms->pdata.caps |= MMC_CAP_NEEDS_POLL; 72290293edSEsben Haabendal } 739c43df57SAnton Vorontsov 749c43df57SAnton Vorontsov dev->platform_data = &oms->pdata; 759c43df57SAnton Vorontsov return dev->platform_data; 769c43df57SAnton Vorontsov err_ocr: 779c43df57SAnton Vorontsov kfree(oms); 789c43df57SAnton Vorontsov return NULL; 799c43df57SAnton Vorontsov } 809c43df57SAnton Vorontsov EXPORT_SYMBOL(mmc_spi_get_pdata); 819c43df57SAnton Vorontsov 829c43df57SAnton Vorontsov void mmc_spi_put_pdata(struct spi_device *spi) 839c43df57SAnton Vorontsov { 849c43df57SAnton Vorontsov struct device *dev = &spi->dev; 859c43df57SAnton Vorontsov struct of_mmc_spi *oms = to_of_mmc_spi(dev); 869c43df57SAnton Vorontsov 87*edd60214SAndy Shevchenko if (!dev->platform_data || !dev_fwnode(dev)) 889c43df57SAnton Vorontsov return; 899c43df57SAnton Vorontsov 909c43df57SAnton Vorontsov kfree(oms); 919c43df57SAnton Vorontsov dev->platform_data = NULL; 929c43df57SAnton Vorontsov } 939c43df57SAnton Vorontsov EXPORT_SYMBOL(mmc_spi_put_pdata); 94