linux/drivers/mmc/host/of_mmc_spi.c
<<
>>
Prefs
   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
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/device.h>
  13#include <linux/slab.h>
  14#include <linux/irq.h>
  15#include <linux/of.h>
  16#include <linux/of_irq.h>
  17#include <linux/spi/spi.h>
  18#include <linux/spi/mmc_spi.h>
  19#include <linux/mmc/core.h>
  20#include <linux/mmc/host.h>
  21
  22MODULE_LICENSE("GPL");
  23
  24struct of_mmc_spi {
  25        struct mmc_spi_platform_data pdata;
  26        int detect_irq;
  27};
  28
  29static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
  30{
  31        return container_of(dev->platform_data, struct of_mmc_spi, pdata);
  32}
  33
  34static int of_mmc_spi_init(struct device *dev,
  35                           irqreturn_t (*irqhandler)(int, void *), void *mmc)
  36{
  37        struct of_mmc_spi *oms = to_of_mmc_spi(dev);
  38
  39        return request_threaded_irq(oms->detect_irq, NULL, irqhandler,
  40                                        IRQF_ONESHOT, dev_name(dev), mmc);
  41}
  42
  43static void of_mmc_spi_exit(struct device *dev, void *mmc)
  44{
  45        struct of_mmc_spi *oms = to_of_mmc_spi(dev);
  46
  47        free_irq(oms->detect_irq, mmc);
  48}
  49
  50struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
  51{
  52        struct mmc_host *mmc = dev_get_drvdata(&spi->dev);
  53        struct device *dev = &spi->dev;
  54        struct of_mmc_spi *oms;
  55
  56        if (dev->platform_data || !dev_fwnode(dev))
  57                return dev->platform_data;
  58
  59        oms = kzalloc(sizeof(*oms), GFP_KERNEL);
  60        if (!oms)
  61                return NULL;
  62
  63        if (mmc_of_parse_voltage(mmc, &oms->pdata.ocr_mask) < 0)
  64                goto err_ocr;
  65
  66        oms->detect_irq = spi->irq;
  67        if (oms->detect_irq > 0) {
  68                oms->pdata.init = of_mmc_spi_init;
  69                oms->pdata.exit = of_mmc_spi_exit;
  70        } else {
  71                oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
  72        }
  73
  74        dev->platform_data = &oms->pdata;
  75        return dev->platform_data;
  76err_ocr:
  77        kfree(oms);
  78        return NULL;
  79}
  80EXPORT_SYMBOL(mmc_spi_get_pdata);
  81
  82void mmc_spi_put_pdata(struct spi_device *spi)
  83{
  84        struct device *dev = &spi->dev;
  85        struct of_mmc_spi *oms = to_of_mmc_spi(dev);
  86
  87        if (!dev->platform_data || !dev_fwnode(dev))
  88                return;
  89
  90        kfree(oms);
  91        dev->platform_data = NULL;
  92}
  93EXPORT_SYMBOL(mmc_spi_put_pdata);
  94